package top.mschen.blog.common.config.auth2;

import com.alibaba.fastjson.JSON;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.util.StringUtils;
import top.mschen.blog.dto.oauth.OAuth2ExceptionExt;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
 *  * If authentication fails and the caller has asked for a specific content type response, this entry point can send one,
 * along with a standard 401 status. Add to the Spring Security configuration as an {@link AuthenticationEntryPoint} in
 * the usual way.
 *
 *
 校验失败返回特定返回值
 用来解决匿名用户访问无权限资源时的异常
 */
public class OAuth2AuthenticationEntryPointExt extends OAuth2AuthenticationEntryPoint {
    private String typeName = "Bearer";
    private String realmName = "oauth";

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        this.doHandle(request, response, authException);
    }

    @Override
    protected ResponseEntity<OAuth2Exception> enhanceResponse(ResponseEntity<OAuth2Exception> response, Exception exception) {
        HttpHeaders headers = response.getHeaders();
        String existing = null;
        if (headers.containsKey("WWW-Authenticate")) {
            existing = this.extractTypePrefix(headers.getFirst("WWW-Authenticate"));
        }

        StringBuilder builder = new StringBuilder();
        builder.append(this.typeName + " ");
        builder.append("realm=\"" + this.realmName + "\"");
        if (existing != null) {
            builder.append(", " + existing);
        }

        HttpHeaders update = new HttpHeaders();
        update.putAll(response.getHeaders());
        update.set("WWW-Authenticate", builder.toString());

        OAuth2Exception oAuth2Exception = response.getBody();
        OAuth2ExceptionExt oAuth2ExceptionExt = new OAuth2ExceptionExt();
        oAuth2ExceptionExt.setError(oAuth2Exception.getOAuth2ErrorCode());
        oAuth2ExceptionExt.setError_description(oAuth2Exception.getMessage());
        if ("invalid_token".equals(oAuth2Exception.getOAuth2ErrorCode())) {
            oAuth2ExceptionExt.setSuccess(false);
            oAuth2ExceptionExt.setDesc("token_expired");
        }
        oAuth2ExceptionExt.setResultMessage(oAuth2Exception.getOAuth2ErrorCode() + "," + oAuth2Exception.getMessage());
        oAuth2ExceptionExt.setResultCode("9999");
        return new ResponseEntity(JSON.toJSONString(oAuth2ExceptionExt), update, response.getStatusCode());
    }

    private String extractTypePrefix(String header) {
        String existing = header;
        String[] tokens = header.split(" +");
        if (tokens.length > 1 && !tokens[0].endsWith(",")) {
            existing = StringUtils.arrayToDelimitedString(tokens, " ").substring(header.indexOf(" ") + 1);
        }

        return existing;
    }

}
